home *** CD-ROM | disk | FTP | other *** search
/ EDUCORP 8 / Educorp2Compilation.sit / educorp2 / Programming (2300, 7000) / 2302 Hacker Disk / Obi / Obi Docs… / Obi Docs…
Encoding:
Text File  |  1989-07-07  |  12.9 KB  |  301 lines  |  [APPL/DcaP]

  1. OBI -- An Object Oriented Preprocessor
  2. for Aztec C on the Apple Macintosh
  3. Keith Rule
  4. 3750 SW 117th #38
  5. Beaverton, OR 97005
  6. 1 (503) 643-5530
  7. tektronix!teklds!keithr
  8.  
  9. October 7, 1985
  10.  
  11. Introduction
  12.  
  13. Obi is an object oriented preprocessor for Aztec C. It allows functions (also called methods or messages) to be applied to data records call objects.  Obi is my attempt at creating a fast and useful object oriented language for the Macintosh. 
  14.  
  15. The current release (V1.0) has several limitations which may reduce its usefulness. These limitations are 1) that all object and C code must be in one file at translation time, 2) there are very few predefined class that currently exist 3) method names must be very short because of the eight character limit  for ID's in Aztec C.
  16.  
  17. On the plus side, 1) it allows for modular programming 2) it is very fast for an object oriented language since there in no interpretation done at run time 3) it is very easy to reuse code.
  18.  
  19. I hope this is a useful program for those of you that have been waiting patiently for an object oriented developement system. Because of the limitations in this release I am releasing it into the public domain. As future versions become more robust they may be released as FreeWare. 
  20.  
  21. Terminology
  22.  
  23. I guess before I dive into this I should say that I am not an expert on object oriented programming nor do I know Smalltalk.  I do believe I am using the terminology the same way it is applied to Smalltalk but if I'm not, well I plead ignorance. 
  24.  
  25. A Class is collection of Objects and Methods or Messages which may be applied to them. An Object is actually a record or structure and a Method is really a function. 
  26.  
  27. Each Class is made up of two kinds of Objects. These are Class objects 
  28. and Instance objects. A Class object always exists. It holds most of the global information the Class needs.  In general it's job is to do things like creating new Instance objects. Instance objects are the individual objects created at runtime. For example if there were a Class WINDOW that knew about Macintosh window, each individual window on the screen would actually correspond to its own Instance object. 
  29.  
  30. Each kind of object has its own kind of variable. The Class object has Class Variables which are thought of as variables global to all Instance objects in the Class. The Instance object has Instance Variables which are unique to each Instance Object.
  31.  
  32. Each kind of object also has its own kind of Method or Message. The Class object has the Class Methods which are functions which can only be applied to Class Objects. The Instance Object has Instance Methods which may only be applied to Instance Objects.
  33.  
  34. Classes also have a superclass which is the class the currently defined class inherits from. All Instance and Class methods and variables that are availible to the Superclass are also availible to the Class. This means that a Class TEWIN whose superclass in WINDOW contains all the varibles of WINDOW and knows about all of its Methods. This is how code is reused in the object oriented environment.
  35.  
  36. There are also three other special keywords that are used in Obi. These are self, super, and object. The word self is used when refering to the current Class while in a Method definition. The word super also refers  to the current Class while in a Method definition, however it also causes the superclasses methods to be executed rather than the objects Classes methods.  The word object is used when defining object variables.
  37.  
  38. There is also one special definition. It is object Generic. It is how  one refers to any (unknown) object. Messages may be sent to an object Generic and since an individual object knows what it is, the correct method will be executed even though there is no actual Generic object.
  39.  
  40. Message are sent to objects using the following syntax : "messageName => obj(arguments)".  This means, apply the Method "messageName" to the  the object "obj". 
  41.  
  42.  
  43. Stucture of Obi Programs
  44.  
  45. A program written in Obi contains a series of Class definitions followed by C code. A Class definition is as follows
  46.  
  47. /*< class CLASSNAME >*/
  48. /*< super SUPERNAME >*/
  49. /*< defines >*/
  50.     Normal C defines required for the Class.
  51.  
  52. /*< variables class
  53.     Normal C varible definitions for the Class Object.
  54. >*/
  55.  
  56. /*< variables instance
  57.     Normal C variable definitions for the Instance Objects.
  58. >*/
  59.  
  60. /*< methods class >*/
  61.     Class method definitions.
  62.  
  63. /*< methods instance >*/
  64.     Instance method definitions.
  65.  
  66.  
  67. All the Class definitions are place at the top of an Obi program. A class which is used as a super to another Class must be define before it is used. The C code is seperated from the Class definitions by several '%'.  Any definitions following '%' are interpreted as C functions.
  68.  
  69. A Sample Class Definition
  70.  
  71. The following object is the Class Object. All objects must inherit from this object either directly or indirectly through its superclass. Object contains no Class or Instance variables. Its only function is to create new objects.
  72.  
  73. /*
  74.  * This is the OBJECT Class. It is the root of
  75.  * all objects.
  76.  */
  77.  
  78. /*< class OBJECT >*/
  79. /*< super NULL >*/
  80.  
  81. /*< defines >*/
  82.  
  83. /*< variables class >*/
  84.  
  85. /*< variables instance >*/
  86.  
  87. /*< methods class */
  88.  
  89. /*
  90.  *  Dynamically create a new object.
  91.  */
  92. object Generic *
  93. new()
  94. {
  95.     object Generic *ptr;
  96.     
  97.     /* get memory for the requested object */
  98.     ptr = (object Generic *) malloc(self.size);
  99.  
  100.     /* make the memory into request object */
  101.     objectify => self(ptr);
  102. }
  103.  
  104. /*
  105.  *  Convert memory into a requested Instance object
  106.  */
  107. objectify(ptr)
  108. object Generic *ptr;
  109. {
  110.     /*
  111.      * Take information from the Class object
  112.      * and fill it in the current Instance object.
  113.      */
  114.     ptr->classType = self.classType;
  115.     ptr->superType = self.superType;
  116.     ptr->size = self.size;
  117.  
  118.     /*
  119.      *  Add pointer to table of Instance Methods.
  120.      */
  121.     ptr->funcTbl = InstTbl;
  122. }
  123.  
  124. /*< methods instance >*/
  125.  
  126. /* None.*/
  127.  
  128. Now lets define a class which has OBJECT as its superclass. This new object will be called TEST and its only funtion will be to view and set an integer .
  129.  
  130. /*< class TEST >*/
  131. /*< super OBJECT >*/
  132.  
  133. /*< defines >*/
  134.  
  135. /*< variables class >*/
  136.  
  137. /*< variables instance 
  138.     int value;
  139. >*/
  140.  
  141. /*< methods class */
  142.  
  143. /* None. */
  144.  
  145. /*< methods instance >*/
  146.  
  147. /*
  148.  *  Set the Instance variable value.
  149.  */
  150. set(value)
  151. int value;
  152. {
  153.     self.value = value;
  154. }
  155.  
  156. /*
  157.  *  Returns the Instance variable value.
  158.  */
  159. view()
  160. {
  161.     return self.value;
  162. }
  163.  
  164.  
  165. Some thing to notice is that methods for a class are referenced via a lookup table. This means that a bizarre type is actually returned from a method so any value must be cast into the correct type. Sorry, its the best I could do in a short time. 
  166.  
  167. Now lets put use the two class in a program. Here is how objects are created and called from a C function. In this case the C function is main().
  168.  
  169. main()
  170. {
  171.     /*
  172.      * Remember, test1 is a pointer to an object and
  173.      * therefore has no actual storage allocated  for it
  174.      * while test2 has storage for an object already
  175.      * allocated and ready for use.
  176.      */
  177.     object TEST *test1, test2;
  178.  
  179.     /* 
  180.      * The message "new" is sent to the Class object
  181.      * "TEST" which dynamically creates a new instance
  182.      * object for Class TEST. Notice the returned value is
  183.      * cast to the correct type.
  184.      */
  185.     test1 = (object TEST *) new => TEST(); 
  186.  
  187.     /*
  188.      *  The message "objectify" sent to the Class object
  189.      *  "TEST" with a pointer to storage large enough 
  190.      *  to hold an instance object of the specified 
  191.      * type Class, turns the raw memory into an 
  192.      * instance object  of type "TEST".
  193.      */
  194.     objectify => TEST(&test2);
  195.  
  196.     /*
  197.      * All references to an object in a message
  198.      * must refer to the object itself. So in the 
  199.      * case where you have a pointer to an object
  200.      *  the pointer must be dereferenced.
  201.      */
  202.     set => *test1(12);  /* set  test1 to 12 */
  203.  
  204.     /* 
  205.      * Since the is the object (not a pointer to
  206.      * one) no dereference is necessary.
  207.      */
  208.     set => test2(13); /* set test2 to 13 */
  209.  
  210.     printf("test1 = %d, test2 = %d\n", (int) view => *test1(),
  211.         (int) view => test2());
  212. }
  213.  
  214. This example will print the following:
  215.             
  216.             "test1 = 12, test2 = 13"
  217.  
  218. The Important things to remember here are that pointers to objects must be dereferenced when applying messages to it and that return values must be cast into the expected return type.
  219.  
  220. How It Really Works
  221.  
  222. In this section I will give an overview of what the C code looks like after  Obi has munged it. It's really fairly straight forward but you probably don't need to know this to use Obi. Though it will help alot when you are debugging code. 
  223.  
  224. The reason Obi is possible at all is because C allows you to casually cast things from one type to another. This means that the C structs for all object have the same first four definitions. These are the classType, superType, size and funcTbl. These are all the definitions required to create and send messages to an object. The definition of object Generic only contains this information. The  actual C structure is -
  225.  
  226.             typedef struct Generic_body (
  227.                 int classType;
  228.                 int superType;
  229.                 int size;
  230.                 FUNC *funcTbl;
  231.             } Generic_body;
  232.  
  233. The structure is actually called Generic_body because all definitions of the form object OBJECTNAME are translated by Obi into OBJECTNAME_body. All Instance objects structures are called OBJECTNAME_body. All Class objects are of the form OBJECTNAME_head.
  234. These may not be the most descriptive names but I'm too lazy to change them. 
  235.  
  236. The definitions self and super are translated into (*receiver).  Super is special though because it affects how a message is translated.
  237.  
  238. Messages of the form "messageName => obj(C args)" are translated into
  239.     (obj).funcTbl[(obj).classType][message_Index](&(obj), C args);
  240.  
  241. Message of the form "message => self(C args)" are translated into
  242.     (*receiver).funcTbl[(*receiver).classType][message_Index](&(*receiver),         C args);
  243.  
  244. Finally message of the form "message => super(C args)" are translated into
  245.     (*receiver).funcTbl[CLASSES_SUPER][message_Index](&(*receiver), C         args);
  246.  
  247. Class Method definitions of the form
  248.     methodName()
  249.     {
  250.     }
  251.  
  252. Become
  253.  
  254.     MmethodName_CLASS(receiver)
  255.     object CLASS *receiver;
  256.     {
  257.     }
  258.  
  259. Instance Method definitions of the form
  260.     methodName()
  261.     {
  262.     }
  263.  
  264. Become
  265.  
  266.     ImethodName_CLASS(receiver)
  267.     object CLASS *receiver;
  268.     {
  269.     }
  270.  
  271. From the above discussions and examples it is probably obvious that I lied a bit in the introduction when I said there is no interpretation done at run time. However the interpretation consists of indexing into an array of function pointers to decide what the proper method is to execute for the current object. The overhead required to do this is fairly small when comparing it to how this is handled in other object programming systems.  I hope you don't feel misled about this. 
  272.  
  273. Command Syntax
  274.  
  275. I originally wrote Obi on a VAX under bsd4.2. Because of this it is a fairly generic Unix application (though I'm not currently interested in porting it to machines other than the Mac under Aztec C). The syntax of the Obi command is: "obi [-v|-t] [-d] filename.obi". The flag "-v" stands for verbose while "-t" stands for terse. They are mutually exclusive flags. The flag "-d" is debug mode for the translator. It causes Methods and messages to generate slightly different code to aid in tracking down "doesNotRespond" errors. 
  276.  
  277. Known Bugs
  278.  
  279. In my rush to get V1.0 out I have found several bugs which aren't fatal but you should be aware of.  These problems will be fixed in the next release.
  280.  
  281. •    Definitions of the form object CLASS aren't properly translated in     both the variables instance and variable class sections. The work    around for this is to use definitions of the form struct    CLASS_body.
  282.  
  283. •    Double quoted strings must not contain an escaped double quote. This     cause Obi to become confused. Also single quotes must not contain an     escaped single quote.
  284.  
  285. •    Error messages leave alot to be desired.
  286.  
  287. •    Method name must be fairly short because of Aztec C's eight     character ID limit.
  288.  
  289. In general I have been testing Obi with "correct" programs so I can't actually say with 100% confidence that it will act sanely for "incorrect" programs.  I have been using it to translate an ~800 line program and I believe I've fixed all the fatal errors and most of the nasty none fatal problems. But who knows?
  290.  
  291. Conclusion
  292.  
  293. Hopefully with this and a demo program is sufficient to get you started with Obi. I plan to improve Obi. There are some obvious improvements to be made to Obi. However, I would definitely like to hear suggestions for improvement to Obi. I am also interested in acquiring interesting CLASS definitions for the Macintosh. If you write an interesting CLASS please send it to me. If you don't want it to become part of the Obi distribution be sure and tell me that too. 
  294.  
  295. If you are still stuck on what object programming is all about try reading  about Smalltalk in May 85 Byte or better yet the article on Software IC's in June 85 Byte. 
  296.  
  297. One Last Thing
  298.  
  299. Nothing I've done in Obi is new or original. I've used techniques that other object oriented preprocessors use. However, I have spent a bit of time writing  this program and would like to get something from distributing it so please send me your opinions (good or bad), any CLASS definitions you think are useful and suggested improvements. 
  300.  
  301. Enjoy